<?php

define('OP_SELECT', 0);
define('OP_DELETE', 1);

/**
 * Lista krotek.
 *
 * @author Rafał Cupał
 * @author Przemysław Furmańczyk
 */
abstract class EntityList {
    protected $dataBase;
    protected $tableName = "";
    
    protected $conditions = array();
    protected $orderColumns = array();
    protected $columns = array();
    protected $joins = array();
    protected $operationType = 0; //SELECT
    protected $limitNumber = -1;
    protected $limitStart = -1;
    
    protected $numRows = 0;
    protected $rows = array();
    
    public function __construct($dataBase, $tableName) {
        $this->dataBase = $dataBase;
        $this->tableName = $tableName;
    }
    
    public function addCondition($condition) {
        $this->conditions[] = $condition;
    }
    
    public function clearConditions() {
        $this->conditions = array();
    }
    
    public function addOrder($columnName, $descending) {
        $this->orderColumns[] = array($columnName, $descending);
    }
    
    public function clearOrder() {
        $this->orderColumns = array();
    }
    
    public function getFields($columnNames) {
        $this->columns = $columnNames;
        $this->columns[] = 'id';
        $this->columns = array_unique($this->columns);
    }
    
    public function setLimit($limitNumber, $limitStart=-1) {
        $this->limitNumber = $limitNumber;
        $this->limitStart = $limitStart;
    }
    
    public function join($tableName, $conditions) {
        $this->joins[] = array($tableName, $conditions);
    }
    
    public function setOperation($type) {
        $this->operationType = $type;
    }
    
    public function getCountRow() {
        return $this->numRows;
    }
    
    public function getResult() {
        return $this->rows;
    }
    
    public function exec() {
        $command = "";
        
        if (count($this->columns)==0) {
            throw new Exception('Entity listy execution error! - ' . 
                    'Not specified columns!');
        }
        
        //Operacja
        switch ($this->operationType) {
            case OP_SELECT:
                $command = 'SELECT ' . 
                    implode(', ', $this->columns) . 
                    ' FROM ' . $this->tableName;
                break;
            case OP_DELETE:
                $command = 'DELETE FROM ' . $this->tableName;
                break;
            default:
                return; //nieznana operacja
        }
        
        //Dołączenia
        foreach ($this->joins as $join_table) {
            $command .= ' JOIN ' . $join_table[0] . ' ON ' . $join_table[1];
        }
        
        //Warunki
        if (count($this->conditions) > 0) {
            $command .= ' WHERE ';
            $command .= implode(' AND ', $this->conditions);
        }
        
        //Sortowanie
        if (count($this->orderColumns) > 0) {
            $command .= ' ORDER BY ';
            $first_order = true;
            foreach ($this->orderColumns as $orderColumn) {
                if (!$first_order) {
                    $command .= ', ';
                }
                $command .= $orderColumn[0] . ($orderColumn[1] ? ' DESC' : ' ASC');
                $first_order = false;
            }
        }
        
        //Limity
        if ($this->limitNumber >= 0) {
            $command .= ' LIMIT ';
            if ($this->limitStart >= 0) {
                $command .= $this->limitStart . ", ";
            }
            $command .= $this->limitNumber;
        }
        
        //Wykonanie operacji
        switch ($this->operationType) {
            case OP_SELECT:
                $statement = $this->dataBase->query($command);
                while ($row = $statement->fetch()) {
                    $this->addRow($row);
                }
                $statement->closeCursor();
                $this->numRows = count($this->rows);
                break;
            case OP_DELETE:
                $this->numRows = $this->dataBase->exec($command);
                break;
            default:
                return; //nieznana operacja
        }
    }
    
    abstract protected function addRow($rowData);
}
